package com.apes.fico.masterdata.gl.service;

import com.alibaba.fastjson.JSONObject;
import com.apes.fico.masterdata.gl.model.AccountingOperatingChart;
import com.apes.fico.masterdata.gl.model.AccountingSystem;
import com.apes.fico.masterdata.gl.respository.AccountingChartDistributionCompanyRepository;
import com.apes.fico.masterdata.gl.respository.AccountingOperatingChartAuxiliaryRepository;
import com.apes.fico.masterdata.gl.respository.AccountingOperatingChartRepository;
import com.apes.framework.api.DomainService;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.util.MapUtil;
import com.apes.scm.masterdata.party.model.PartyRole;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @ClassName AccountingOperatingChartService
 * @Description TODO
 * @Author pengyb
 * @Date 2018/12/27 14:02
 * @Version 1.0
 **/
@Service("accountingOperatingChartService")
public class AccountingOperatingChartService extends DomainService {
    @Autowired
    private AccountingOperatingChartRepository accountingOperatingChartRepository;
    @Autowired
    private AccountingOperatingChartAuxiliaryRepository accountingOperatingChartAuxiliaryRepository;
    @Autowired
    private AccountingChartDistributionCompanyRepository accountingChartDistributionCompanyRepository;

    /**
     * 保存
     *
     * @param request
     * @return
     */
    public AccountingOperatingChart save(SimpleRequest request) {
        AccountingOperatingChart accountingOperatingChart = request.getO(AccountingOperatingChart.class);
        accountingOperatingChart.setCreateDate(new Date());
        accountingOperatingChart.setId(accountingOperatingChart.getCompany().getId() + "." + accountingOperatingChart.getCode());
        return accountingOperatingChartRepository.saveAndFlush(accountingOperatingChart);
    }

    /**
     * 修改
     *
     * @param request
     * @return
     */
    public AccountingOperatingChart update(SimpleRequest request) {
        //checkData(request);
        AccountingOperatingChart accountingOperatingChart = request.getO(AccountingOperatingChart.class);
        accountingOperatingChart.setUpdateDate(new Date());
        return accountingOperatingChartRepository.saveAndFlush(accountingOperatingChart);
    }

    /**
     * 删除
     *
     * @param request
     * @return
     */
    public String delete(SimpleRequest request) {
        AccountingOperatingChart accountingOperatingChart = request.getO(AccountingOperatingChart.class);
        accountingOperatingChartRepository.delete(accountingOperatingChart.getId());
        return "删除成功";
    }

    /**
     * 检查
     *
     * @param request
     */
    public void checkData(SimpleRequest request) {
        AccountingOperatingChart accountingOperatingChart = accountingOperatingChartRepository.findOne((String) request.get("id"));
        if (accountingOperatingChart == null)
            throw new RuntimeException("运营科目" + accountingOperatingChart.getId() + "不存在");
        if (accountingOperatingChart.getVersion() != (int) request.get("version"))
            throw new RuntimeException("运营科目" + accountingOperatingChart.getId() + "已更新或已删除");
    }

    /**
     * 查询末级科目
     *
     * @param request
     * @return
     */
    public List<Map<String, Object>> findByFinalFlag(SimpleRequest request) {
        JSONObject reqJSON = request.getJO();
        String code = reqJSON.getString("key");
        String company = reqJSON.getString("company");
        if (code.isEmpty()) throw new RuntimeException("请输入科目代码或者科目名称！");
        List<Map<String, Object>> operatingCharts = accountingOperatingChartRepository.findByCompanyAndCodeOrName(company, code);

        operatingCharts.stream().forEach((Map<String, Object> item) -> {
            boolean bAuxFlag = (boolean) item.get("auxFlag");
            if (bAuxFlag) {
                item.put("aux", accountingOperatingChartAuxiliaryRepository.findByAccOperatingChartId(item.get("id").toString()));
            }
        });
        return operatingCharts;
    }

    /**
     * 运营科目表查询
     *
     * @param request
     * @return
     */
    public List<Map<String, String>> findAllAccOperChart(SimpleRequest request) {
        Map fieldMap = new HashMap();
        String company = null;
        try {
            company = request.get("company");
            fieldMap.put("company", company);
        } catch (Exception e) {

        }
        List<Map> fields = request.get("condition");
        if (fields.isEmpty() && company == null) throw new RuntimeException("请输入公司");
        fields.stream().forEach(field -> {
            if (field.get("field").toString().equals("company.id")) {
                fieldMap.put("company", field.get("value").toString());
            }
            if (field.get("field").toString().equals("accGroup.id")) {
                fieldMap.put("accGroup", field.get("value").toString());
            }

        });

        if (fieldMap.containsKey("company") == false) throw new RuntimeException("请输入公司！");
        company = fieldMap.get("company").toString();
        String accGroup = null;
        if (fieldMap.containsKey("accGroup")) {
            accGroup = fieldMap.get("accGroup").toString();
        }

        List<Map<String, String>> accountingOperatingCharts;
        if (accGroup == null || accGroup == "") {
            accountingOperatingCharts = accountingOperatingChartRepository.findByCompany_Id(company);
        } else {
            accountingOperatingCharts = accountingOperatingChartRepository.findByCompany_IdAndAccGroup_Id(company, accGroup);
        }
        if (accountingOperatingCharts.size() != 0 || !accountingOperatingCharts.isEmpty()) {
            String rule = accountingChartDistributionCompanyRepository.findByCompany_Id(company).getAccSystem().getAccIdRule();
            accountingOperatingCharts.stream().forEach(accOPChart -> {
                accOPChart.put("path", getPath(rule, accOPChart.get("code").toString()));
            });
        }
        return accountingOperatingCharts;
    }

    public AccountingOperatingChart findAccountingOperatingChart(PartyRole company, AccountingSystem accountingSystem, String charCode) {
        Map filters = MapUtil.mapper("company", company, "accSystem", accountingSystem, "code", charCode);
        return accountingOperatingChartRepository.findOne(JpaDsl.toCriteria(filters)).orElse(null);
    }

    private String getPath(String rule, String code) {
        List l = Arrays.asList(rule.split("/"));
        int iLen = 0;
        String path = "";
        int iKMID = code.length();
        for (int i = 0; i < l.size(); i++) {
            int j = Integer.parseInt(l.get(i).toString());
            if (iLen + j > iKMID) {
                break;
            }
            String pathCODE = code.substring(iLen, iLen + j);
            path = path != "" ? path + "/" + pathCODE : pathCODE;
            iLen = iLen + j;
        }
        return path;
    }

    /**
     * 根据公司下拉查询
     *
     * @param request
     * @return
     */
    public List<Map<String, Object>> findByCompany(SimpleRequest request) {
        JSONObject reqJSON = request.getJO();
        String company = reqJSON.getString("company");
        if (company.isEmpty()) throw new RuntimeException("请输入公司！");
        List<Map<String, Object>> operatingCharts = accountingOperatingChartRepository.findByCompany(company);
        operatingCharts.stream().forEach((Map<String, Object> item) -> {
            boolean bAuxFlag = (boolean) item.get("auxFlag");
            if (bAuxFlag) {
                item.put("aux", accountingOperatingChartAuxiliaryRepository.findByAccOperatingChartId(item.get("id").toString()));
            }
        });
        return operatingCharts;
    }

    /**
     * 查询所有运营科目 财务凭证明细报表使用
     * @param request
     * @return
     */
    public Page<Map> findAllDistinct(SimpleRequest request) {
        Page<Map> accountingOperatingCharts = accountingOperatingChartRepository.findAllDistinctCode(request.get("key"),PageRequest.of(request.get("page"), request.get("size")));
        List<Map> content = mapKeysToLowerCase(accountingOperatingCharts.getContent(), "lower");
//        ArrayList<AccountingOperatingChart> collect = accountingOperatingCharts.getContent()
//                .stream()
//                .collect(
//                        Collectors.collectingAndThen(
//                                Collectors.toCollection(
//                                        () -> new TreeSet<>(
//                                                Comparator.comparing(tc -> tc.getName())
//                                        )
//                                ), ArrayList::new
//                        )
//                );
        PageImpl page = new PageImpl<>(content, PageRequest.of(request.get("page"), request.get("size")), content.size());
        return page;
    }

    /**
     * 将List里面的Map的key 做大小写转换
     * @param mapList 数据
     * @param type upper 小写转大写 lower 大写转小写
     * @return
     */
    public List<Map> mapKeysToLowerCase(List<Map> mapList, String type){
        List<Map> returnList = new ArrayList<>(mapList.size());

        mapList.forEach(map -> {
            Map<String,String> returnMap = new HashMap<>(map.size());
            //将大写转换为小写
            if (Objects.equals("upper",type)){
                map.forEach((key,val) -> returnMap.put(String.valueOf(key).toUpperCase(),String.valueOf(val)));
            }else{
                map.forEach((key,val) -> returnMap.put(String.valueOf(key).toLowerCase(),String.valueOf(val)));
            }
            returnList.add(returnMap);
        });
        return returnList;
    }
}
